package com.lancoo.edu.platform.operation.commons.service.bo.sys;

import com.lancoo.edu.platform.operation.commons.config.LancooConfig;
import com.lancoo.edu.platform.operation.commons.constant.SystemConstant;
import com.lancoo.edu.platform.operation.commons.domain.vo.sys.FileVo;
import com.lancoo.edu.platform.operation.commons.exception.ServiceException;
import com.lancoo.edu.platform.operation.commons.utils.FileUtil;
import com.lancoo.edu.platform.operation.commons.utils.TimeUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author lzh
 * 文件信息业务逻辑
 */
@Service
@AllArgsConstructor
public class FileBoService {

    @Resource
    private final LancooConfig lancooConfig;

    /**
     * 批量保存文件
     * @param files 文件列表
     * @param modelName 模块名
     * @return 保存后的文件列表信息
     * @throws Exception IOException、ServiceException
     */
    @Transactional(rollbackFor = Exception.class)
    public List<FileVo> batchSave(List<MultipartFile> files, String modelName) throws Exception {
        List<FileVo> fileList = new ArrayList<>();
        for(MultipartFile file : files) {
            // 1.获取文件类型
            String filename = FileUtil.getFilename(file);
            if(StringUtils.isBlank(filename)) {
                throw new ServiceException("文件名不可为空或文件名格式不正确");
            }
            // 2.获取文件归类
            String fileClassify = FileUtil.getFileClassify(filename);
            // 3. 获取新文件名
            String newFilename = FileUtil.getNewFilename(filename);
            // 4.保存文件到本地并返回相对地址
            String url = save(file, newFilename, fileClassify, modelName);
            // 5. 拼接访问地址【协议 ://ip：端口号/根地址/文件目录(upload/news/images/2021/09/17/xxx.jpg)】
//            url = scheme + "://" + ip + ":" + port + lancooConfig.getContextPath() + lancooConfig.getFileMapping() + url;
            url = lancooConfig.getServiceUrl() + lancooConfig.getFileMapping() + url;
            // 6. 设置并加入文件返回列表
            FileVo fileBo = new FileVo(filename, file.getSize(), url, fileClassify);
            fileList.add(fileBo);
        }
        return fileList;
    }


    /**
     * 保存文件
     * @param file 文件
     * @param fileName 文件名
     * @param fileClassify 文件归类，如image、video、file、voice
     * @param modelName 模块名，用于区分各个模块的文件
     * @return 文件保存后的相对
     * @throws Exception IO等异常
     */
    public String save(MultipartFile file, String fileName, String fileClassify, String modelName) throws Exception {
        // 1..后半段目录：  2021/09/17
        String dateDir = TimeUtil.dateForStr(new Date());
        // 2.文件保存目录  /images/2021/09/17
        String savePath = lancooConfig.getFileSavePath() + modelName + "/" + fileClassify + "/" + dateDir;
        File dir = new File(savePath);
        if (!dir.exists()) {
            if(!dir.mkdirs()) {
                throw new ServiceException("文件夹创建失败");
            }
        }
        // 3.创建这个新文件
        File newFile = new File(savePath + fileName);
        // 4.将文件写到指定的相对路径;
        file.transferTo(newFile.getAbsoluteFile());
        // 5.返回映射后的相对地址
        return modelName + "/" + fileClassify + "/" + dateDir + fileName;
    }

    /**
     * 设置相对地址
     * 如：http://localhost:11110/info-collect/upload/vote/file/2021/09/17/f3fc341d6dd.txt
     * 则截取‘/upload’后的相对地址（包括‘/upload’）
     * @param url 要设置的绝对地址
     * @return 相对地址
     */
    public String setRelativeUrl(String url) {
        if(StringUtils.isBlank(url)) {
            return url;
        }
        if(url.contains(lancooConfig.getFileMapping())) {
            int index = url.indexOf(lancooConfig.getFileMapping());
            return index == -1 ? null : url.substring(index);
        }
        return url;
    }

    /**
     * 设置相对地址
     * 如：http://localhost:11110/info-collect/upload/vote/file/2021/09/17/f3fc341d6dd.txt
     * 则截取‘/upload’后的相对地址（包括‘/upload’）
     * @param url 要设置的绝对地址
     * @return 相对地址
     */
    public String setRelativeUrl2(String url) {
        if(StringUtils.isNotBlank(url)) {
            if(url.contains(lancooConfig.getContextPath() + lancooConfig.getFileMapping())) {
                int index = url.indexOf(lancooConfig.getFileMapping());
                return index == -1 ? null : url.substring(index);
            }
            return url;
        }
        return null;
    }

    /**
     * 设置绝对地址
     * 如：http://localhost:11110/info-collect/upload/vote/file/2021/09/17/f3fc341d6dd.txt
     * 则截取‘/upload’后的相对地址（包括‘/upload’）
     * @param url 要设置的绝对地址
     * @param sysId 系统ID
     * @return 相对地址
     */
    public String setAbsoluteUrl(String url, String sysId) {
        if(StringUtils.isBlank(url) || url.contains(SystemConstant.HTTP_PROTOCOL) || url.contains(SystemConstant.HTTPS_PROTOCOL)) {
            return url;
        }
        String serviceUrl = lancooConfig.getRootUrl(sysId);
        if(StringUtils.isBlank(serviceUrl)) {
            return url;
        }
        return serviceUrl + url;
    }


}
